package com.bitmapgame;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.view.View;

public class BallRenderer extends View
{
    private Marble marble;
    private Paddle paddle;
    private BasicBrick brick;

    public boolean initializationNeeded = true;
    public boolean failCondition = false;

    private Bitmap marbleBitmap;
    private Bitmap paddleBitmap;
    private Bitmap brickBitmap;

    public int bounces = 0;

    public BallRenderer(Context context)
    {
        super(context);

        //Register marble and paddle bitmaps and objects
        marbleBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.gray_marble);
        paddleBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.gray_paddle);
        brickBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.blue_brick);

        paddle = new Paddle(0, 0);
    }

    private void InitializeCanvas(Canvas canvas)
    {
        int paddleX = canvas.getWidth() / 2 - paddleBitmap.getWidth() / 2;
        int paddleY = canvas.getHeight() - paddleBitmap.getHeight();
        paddle.SetX(paddleX);
        paddle.SetY(paddleY);
        paddle.SetXVel(0);

        int marbleX = (canvas.getWidth() / 2) - (marbleBitmap.getWidth() / 2);
        int marbleY = paddle.GetY() - marbleBitmap.getHeight() - 1;
        marble = new Marble(marbleX, marbleY);
        marble.ResetVel();

        brick = new BasicBrick(canvas.getWidth() / 2 - brickBitmap.getWidth() / 2, 200);

        failCondition = false;
        bounces = 0;

        initializationNeeded = false;
    }

    public void SetXAccel(double x)
    {
        paddle.SetXVel(x);
    }

    private boolean PaddleHitBall()
    {
        //Return true if marble is between paddle edges
        //and the bottom of marble is at or below the paddle
        return paddle.GetX() < marble.GetX() + marbleBitmap.getWidth()
                && marble.GetX() < paddle.GetX() + paddleBitmap.getWidth()
                && marble.GetY() + marbleBitmap.getHeight() >= paddle.GetY()
                && marble.GetY() + marbleBitmap.getHeight() / 2 <= paddle.GetY();
    }

    private void BounceBallOffPaddle(Canvas canvas)
    {
        marble.InvertYVel();
        marble.SetY(canvas.getHeight() - paddleBitmap.getHeight() - marbleBitmap.getHeight());
        marble.SetXVel(((marble.GetX() + marbleBitmap.getWidth() / 2) - (paddle.GetX() + paddleBitmap.getWidth() / 2)) / 5);

        bounces += 1;
    }

    private void MarbleCollision(Canvas canvas)
    {
        //Detects if marble hits a wall, brick, or paddle and bounces off
        if(marble.GetX() <= 0)
        {
            marble.InvertXVel();
            marble.SetX(0);
        }
        if(marble.GetX() + marbleBitmap.getWidth() >= canvas.getWidth())
        {
            marble.InvertXVel();
            marble.SetX(canvas.getWidth() - marbleBitmap.getWidth());
        }
        if(marble.GetY() <= 0)
        {
            marble.InvertYVel();
        }

        if(PaddleHitBall())
        {
            BounceBallOffPaddle(canvas);
        }
    }

    private void MovePaddle(Canvas canvas)
    {
        //Move paddle based on accelerometer data
        double accelDeadZone = .5;
        int sensitivityMultiplier = 10;
        if(paddle.GetX() >= 0 && paddle.GetX() <= canvas.getWidth() - paddleBitmap.getWidth())
        {
            if(Math.abs(paddle.GetXVel()) > accelDeadZone)
            {
                paddle.SetX((int) (paddle.GetX() - paddle.GetXVel() * sensitivityMultiplier));
            }
        }

        if(paddle.GetX() < 0)
        {
            paddle.SetX(0);
        }
        else if(paddle.GetX() > canvas.getWidth() - paddleBitmap.getWidth())
        {
            paddle.SetX(canvas.getWidth() - paddleBitmap.getWidth());
        }
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        super.onDraw(canvas);

        //Set initial values for marble and paddle
        if(initializationNeeded)
        {
            InitializeCanvas(canvas);
        }

        MarbleCollision(canvas);

        //Move marble
        marble.SetX((int) (marble.GetX() + marble.GetXVel()));
        marble.SetY((int) (marble.GetY() + marble.GetYVel()));

        //If marble goes off bottom of screen, reset game
        if(marble.GetY() > canvas.getHeight())
        {
            failCondition = true;
            return;
        }

        MovePaddle(canvas);

        //Draw paddle and marble
        canvas.drawBitmap(marbleBitmap, marble.GetX(), marble.GetY(), null);
        canvas.drawBitmap(paddleBitmap, paddle.GetX(), paddle.GetY(), null);
        canvas.drawBitmap(brickBitmap, brick.GetX(), brick.GetY(), null);
    }
}
